<?php

global $g_boot_time;
$g_boot_time = microtime(true);

define('UC_API_VERSION', '1.0.0');          // UCenter 版本标识

define('UC_API_RETURN_SUCCEED', '1');
define('UC_API_RETURN_FAILED', '-1');
define('UC_API_RETURN_FORBIDDEN', '-2');

$app_config = require(dirname(dirname(__FILE__)) . '/community/config/boot.php');
require($app_config['CONFIG_DIR'] . '/ucenter_config.php');
error_reporting(0);
set_magic_quotes_runtime(0);

if (!isset($_GET['code']))
{
    exit(UC_API_RETURN_FORBIDDEN);
}

// 将来自 UC 的请求解码为查询参数
$args = array();
parse_str(_authcode($_GET['code'], 'DECODE', UC_KEY), $args);

// 检查是否提供了查询参数
if(empty($args) || !isset($args['action']))
{
    exit('Invalid Request');
}

// 检查请求是否超时
if(!isset($args['time']) || time() - $args['time'] > 3600)
{
    exit('Authracation has expiried');
}

// 解析参数
require_once UC_CLIENT_DIR . '/lib/xml.class.php';
$post = xml_unserialize(file_get_contents('php://input'));
$_GET = $args;
if (is_array($post))
{
    $_POST = $post;
}

// 构造应用程序，执行 UC API 请求
require_once $app_config['QEEPHP_DIR'] . '/library/q.php';
require_once $app_config['ROOT_DIR'] . '/app/myapp.php';
$app = CommunityApp::instance($app_config);

#IFDEF DEBUG
QLog::log('$args: ' . http_build_query($args), QLog::DEBUG);
if (is_array($post) && !empty($post))
{
    QLog::log('$post: ' . http_build_query($post), QLog::DEBUG);
}
#ENDIF

// 检查请求的 API 是否允许使用
$enabled_api = Q::normalize(Q::ini('appini/ucenter/enabled_api'));
$api = $args['action'];

#IFDEF DEBUG
QLog::log('Enabled UCenter API: ' . implode(', ', $enabled_api), QLog::DEBUG);
QLog::log('Called API: ' . $api);
#ENDIF

if (!in_array($api, $enabled_api))
{
    #IFDEF DBEUG
    QLog::log('UC_API_RETURN_FORBIDDEN', QLog::DEBUG);
    #ENDIF

    // 请求的 API 不允许执行
    exit(UC_API_RETURN_FORBIDDEN);
}

// 执行动作
Q::changeIni('dispatcher_url_mode', QContext::URL_MODE_STANDARD);
$context = QContext::instance();
$controller_name = Q::ini('appini/ucenter/api_controller_name', 'ucenter');
$context->changeRequestUDI("{$controller_name}/{$api}");

#IFDEF DEBUG
QLog::log('REQUEST URI: ' . $context->requestUri(), QLog::DEBUG);
#ENDIF

$ret = $app->dispatching();

if (strlen($ret) == 0)
{
    $ret = UC_API_RETURN_FAILED;
}

exit($ret);


/**
 * 解码 UC 请求字符串
 */
function _authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)
{
    $ckey_length = 4;

    $key = md5($key ? $key : UC_KEY);
    $keya = md5(substr($key, 0, 16));
    $keyb = md5(substr($key, 16, 16));
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';

    $cryptkey = $keya.md5($keya.$keyc);
    $key_length = strlen($cryptkey);

    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
    $string_length = strlen($string);

    $result = '';
    $box = range(0, 255);

    $rndkey = array();
    for($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }

    for($j = $i = 0; $i < 256; $i++) {
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }

    for($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }

    if($operation == 'DECODE') {
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
            return substr($result, 26);
        } else {
                return '';
            }
    } else {
        return $keyc.str_replace('=', '', base64_encode($result));
    }
}

